/**
 * Window popup module with modal dialog
 * Maximum window popup = 10 dialog
 *
 * @namespace ISS.Popup
 * @module Popup
 * @requires ISS
 * @require	dispatcher
 * @requires popup.css
 * @requires jquery
 * @requires event
 * @requires dom
 * @requires connection
 */

ISS.namespace("Popup");
(function() {
	$L = ISS.lang,

	// Constants
	constants = {
		LOADING_IMAGE : location.href.substr(0, location.href.search("index.php")) + 'media/images/loadingAnimation.gif',
		SMALL_LOADING_IMAGE : location.href.substr(0, location.href.search("index.php")) + 'media/images/loading.gif',
		// Default dialog size
		WIDTH: 630,
		HEIGHT: 440,
		
		// Modal
		MODAL_DIALOG: true,
		NO_MODAL_DIALOG: false,
		
		// Configuration structure
		STACK_INDEX: 0,
		STACK_WINDOW: 1,
		STACK_URI: 2,
		STACK_PARAM: 3,
		STACK_WIDTH: 4,
		STACK_HEIGHT: 5,
		STACK_MODAL: 6,
		STACK_CALLBACK: 7
	};

	// Initialize loading image
	imgLoader = new Image();		// preload image
	imgLoader.src = constants.LOADING_IMAGE;
	
	imgSmallLoader = new Image();
	imgSmallLoader.src = constants.SMALL_LOADING_IMAGE;

	/**
	 * The popup windows
	 * @class Windows
	 * @static
	 */
	ISS.Popup.Windows = function() {
		var obj = {},
		stack = [],
	  	
	  	SS_WIDTH = 0,
	  	SS_HEIGHT = 0;
	  	
		/**
		* @description Hide top position modal dialog
		* @method Hide_Modal
		* @public
		* @param {String} selector	Selector id
		* @param {String} callback	Used to running callback after hide modal
		* @return void
		*/
	  	obj.Hide_Modal = function(selector, callback) {
	  		if (typeof selector=="undefined") {
	  			selector = '';
	  		}
	  		// Remove top modal
	  		if (selector=='' || selector==null) {
	  			if (stack.length>0) {	  				
	  				var config = stack.pop();
	  				_Remove('#' + config.window);
	  			}
	  		}
	  		else {
	  			_Remove(selector);
	  		}
	  		// Callback for run after hide modal
	  		if (callback!=null) {
	  			eval(callback);
	  		}
	  	};
	  	
	  	/**
		 * @description Show modal dialog on top screen, maximum modal is 10 dialog 
		 * @method Show_Modal
		 * @public
		 * @param {String} caption The caption dialog
		 * @param {String} uri Remote URL
		 * @param {Object} param Used to pass the user parameter
		 * @param {int} width Modal dialog width
		 * @param {int} hight Modal dialog hight
		 * @param {String} callback Function want to call after open dialog completed
		 * @return void
		 */
		obj.Show_Modal = function (caption, uri, param, width, hight, callback) {
			// Check for maximum modal dialog
			if (stack.length<10) {
				try {
					// Keep configuration
					var config = {
							index: stack.length + 1,
							window: 'SS_window' + (stack.length + 1),
							overlay: 'SS_overlay' + (stack.length + 1),
							uri: uri,
							param: param,					
							width: width,
							hight: hight,
							modal: constants.MODAL_DIALOG,					
							callback: callback
					};
					
					stack.push(config);
					// Define selector
					selector = "#" + config.window;
					
					// Check for browser limitation
					if (typeof document.body.style.maxHeight === "undefined") {//if IE 6
						$("body","html").css({height: "100%", width: "100%"});
						$("html").css("overflow","hidden");
						if (document.getElementById("SS_HideSelect") === null) {//iframe to hide select elements in ie6
							$("body").append("<iframe id='SS_HideSelect'></iframe><div id='"+ config.overlay +"'></div><div id='"+ config.window +"'></div>");
						}
					}else{//all others
						if(document.getElementById(config.overlay) === null){
							$("body").append("<div id='"+ config.overlay +"'></div><div id='"+ config.window +"'></div>");
						}							
					}
					
					if(_DetectMacXFF()){
						$("#" + config.overlay).addClass("SS_overlayMacFFBGHack");//use png overlay so hide flash
					}else{
						$("#" + config.overlay).addClass("SS_overlayBG");//use background and opacity
					}
									
					if(caption===null){caption="";}
					
					// Display loading image 
					$("body").append("<div id='SS_load'><img src='"+imgLoader.src+"' /></div>");//add loader to the page
					$('#SS_load').show();//show loader
	
					// Generate uri with kohana format
					var uri = ISS.Ajax.Dispatcher.augmentURI(config.uri, config.param); 
	
					// Define dialog size
					SS_WIDTH = (config.width*1) + 30 || constants.WIDTH; 	//defaults to 630 if no paramaters were added to URL
					SS_HEIGHT = (config.hight*1) + 40 || constants.HEIGHT; 	//defaults to 440 if no paramaters were added to URL
					ajaxContentW = SS_WIDTH - 30;
					ajaxContentH = SS_HEIGHT - 45;
					
					// Add modal
					if($(selector).css("display") != "block"){
						if (config.modal != constants.MODAL_DIALOG){	//ajax no modal
							$(selector).append("<div id='SS_title'><div id='SS_ajaxWindowTitle'>"+caption+"</div><div id='SS_closeAjaxWindow'><a href='#' id='SS_closeWindowButton'>close</a> or Esc Key</div></div><div id='SS_ajaxContent' style='width:"+ajaxContentW+"px;height:"+ajaxContentH+"px'></div>");
						}else{//ajax modal
							$("#" + config.overlay).unbind();
							$(selector).append("<div id='SS_ajaxContent' class='SS_modal' style='width:"+ajaxContentW+"px;height:"+ajaxContentH+"px;'></div>");	
						}
					}else{//this means the window is already up, we are just loading new content via ajax
						$("#SS_ajaxContent")[0].style.width = ajaxContentW +"px";
						$("#SS_ajaxContent")[0].style.height = ajaxContentH +"px";
						$("#SS_ajaxContent")[0].scrollTop = 0;
						$("#SS_ajaxWindowTitle").html(caption);
					}
					// Adjust dialog position
					$("div" + selector + " div.SS_modal").load(uri,function(){//to do a post change this load method
						_Position(selector);
						// Remove loading image
						$("#SS_load").remove();
						// Show modal
						$(selector).css({display:"block"});
					});
					
					// If not modal defind exit key listening
					if(!config.modal){
						document.onkeyup = function(e){ 	
							if (e == null) { // ie
								keycode = event.keyCode;
							} else { // mozilla
								keycode = e.which;
							}
							if(keycode == 27){ // close
								_Remove(selector);
							}	
						};
					}
					
					// Callback function after open dialog
	  				if(config.callback!=null) {
	  					eval(config.callback);
	  				}
	
				} catch(e) {
					//nothing here
				}
			}
			else {
				alert ("Maximum modal dialog is 10 modal. Can't create new dialog.");
			}
				
		};
		
		/**
		 * @description Show loding icon on center page area 
		 * @method Show_Loading
		 * @public
		 * @return void
		 */
		obj.Show_Loading = function () {
			if(document.getElementById('SS_loading') === null) {
				// Get page size
				var pageSize = _GetPageSize();
				// Get scholler position
				var schollPosition = _GetScrollXY();
				// Append image
				$("body").append("<div id='SS_loading'><img src='"+imgSmallLoader.src+"' /></div>");
				// Calculate position
				$('#SS_loading').css({position: 'absolute', left: parseInt(schollPosition[0]) + parseInt((pageSize[0] / 2),10) + 'px'});
				$('#SS_loading').css({position: 'absolute', top: parseInt(schollPosition[1]) + parseInt((pageSize[1] / 2),10) + 'px'});
				//show loading
				$('#SS_loading').show();	
			}
		};

		/**
		 * @description Hide loding icon 
		 * @method Hide_Loading
		 * @public
		 * @return void
		 */
		obj.Hide_Loading = function () {
			//hide loding
			$('#SS_loading').remove();		
		};
		
		/**
		 * @description Get scholling offset
		 * @method _GetScrollXY
		 * @private
		 * @return {Object} Array [X,Y] : X is horizontal scholling position, Y is vertical scholling position
		 */
		function _GetScrollXY() {
			  var scrOfX = 0, scrOfY = 0;
			  if( typeof( window.pageYOffset ) == 'number' ) {
			    //Netscape compliant
			    scrOfY = window.pageYOffset;
			    scrOfX = window.pageXOffset;
			  } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
			    //DOM compliant
			    scrOfY = document.body.scrollTop;
			    scrOfX = document.body.scrollLeft;
			  } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
			    //IE6 standards compliant mode
			    scrOfY = document.documentElement.scrollTop;
			    scrOfX = document.documentElement.scrollLeft;
			  }
			  return [ scrOfX, scrOfY ];
			}

		/**
		 * @description Callback function
		 * @method _callback
		 * @private
		 * @param {Function} func the callback function 
		 * @param {Object} opts an object literal with the following 
		 * properties (all optional): 
		 * bind: the object to bind the function to (what the "this" keyword will refer to) 
		 * args: an array of arguments to pass to the function when it is called, these will be 
		 * appended after any arguments passed by the caller 
		 * @return {boolean} boolean, whether to supress the arguments passed by the caller. This default is false. 
		 */
		function _callback(func,opts){ 
			var cb = function(){ 
				var args = opts.args ? opts.args : []; 
				var bind = opts.bind ? opts.bind : this; 
				var fargs = opts.supressArgs === true ? [] : _toArray(arguments); 
				func.apply(bind,fargs.concat(args)); 
			}; 
			return cb; 
		}; 
		
		/**
		 * @description Convert to array a utility function for callback()
		 * @method _toArray
		 * @private
		 * @param {Object} arrayLike The similar array object
		 * @return {Object} Array object
		 */
		function _toArray(arrayLike){ 
			var arr = []; 
			for(var i = 0; i < arrayLike.length; i++){ 
				arr.push(arrayLike[i]); 
			} 
			return arr; 
		};
	  	
		/**
		 * @description Remove dialog content
		 * @method _Remove
		 * @private
		 * @param {String} selector The selector id name
		 * @return void
		 */
		function _Remove(selector) {
			if(selector===null) {
				selector = "#SS_window";
			}
		 	$("#SS_imageOff").unbind("click");
			$("#SS_closeWindowButton").unbind("click");
			$(selector).fadeOut("fast",function(){
				// Remove dialog
				$(selector).remove();
				$('#SS_overlay' + (stack.length+1)).remove();
			});
			// Remove loading image
			$("#SS_load").remove();
			if (typeof document.body.style.maxHeight == "undefined") {//if IE 6
				$("body","html").css({height: "auto", width: "auto"});
				$("html").css("overflow","");
			}
			document.onkeydown = "";
			document.onkeyup = "";
			return false;
		};
		
		/**
		 * @description Adjust position of dialog
		 * @method _Position
		 * @private
		 * @param {String} selector The selector id name
		 * @return void
		 */
		function _Position(selector) {
			if(selector===null) {
				selector = "#SS_window";
			}
			// Calulate and adjust position
			$(selector).css({marginLeft: '-' + parseInt((SS_WIDTH / 2),10) + 'px', width: SS_WIDTH + 'px'});
			if ( !(jQuery.browser.msie && jQuery.browser.version < 7)) { // take away IE6
				$(selector).css({marginTop: '-' + parseInt((SS_HEIGHT / 2),10) + 'px'});
			}
		};
		
		/**
		 * @description Get current page size
		 * @method _GetPageSize
		 * @private
		 * @return {Object} Array of page size
		 */
		function _GetPageSize(){
			var de = document.documentElement;
			var w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
			var h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;
			arrayPageSize = [w,h];
			return arrayPageSize;
		};

		/**
		 * @description Detecting mac or firefox browser
		 * @method _DetectMacXFF
		 * @private
		 * @return {boolean} true if mac or firefox othervise return false.
		 */
		function _DetectMacXFF() {
		  var userAgent = navigator.userAgent.toLowerCase();
		  if (userAgent.indexOf('mac') != -1 && userAgent.indexOf('firefox')!=-1) {
		    return true;
		  }
		};
		
		/**
		 * @description Add ISS to href & area elements that have a class of .ISS
		 * @method _Init
		 * @private
		 * @param {Object} domChunk
		 * @return {boolean} true if mac or firefox othervise return false.
		 */		
		function _Init(domChunk){
			$(domChunk).click(function(){
			var t = this.title || this.name || null;
			var a = this.href || this.alt;
			var g = this.rel || false;
			obj.Show_Modal(t,a,g); //caption, uri, param, width, hight, modal, callback
			this.blur();
			return false;
			});
		}
		
	  	/**
		* @description Returns a string representing the soft square popup.
		* @method toString
		* @return {String}
		*/
		obj.toString = function() {
		    return ("Soft Square Popup Windows");
		};

		return obj;
	}();
	
	/********************** End ISS.Popup.Windows Class **********************/

})();